# -*- coding: utf-8 -*-

from MyGraph import MyGraph
# from MyGraph_GPU import MyGraph

class MetabolicNetwork(MyGraph):
    
    def __init__(self, network_type = "metabolite-reaction", split_rev = False):
        MyGraph.__init__(self)
        self.net_type = network_type
        self.node_types = {}
        if network_type == "metabolite-reaction":
            self.node_types["metabolite"] = []
            self.node_types["reaction"] = []
        self.split_rev =  split_rev
    
    def add_vertex_type(self, v, nodetype):
        self.add_vertex(v)
        self.node_types[nodetype].append(v)
    
    def get_nodes_type(self, node_type):
        return self.node_types.get(node_type,None)
    
    def load_from_file(self, filename):
        rf = open(filename)
        gmr = MetabolicNetwork("metabolite-reaction")
        for line in rf:
            if ":" in line:
                tokens = line.split(":")
                reac_id = tokens[0].strip()
                gmr.add_vertex_type(reac_id, "reaction")
                rline = tokens[1]
            else:
                raise Exception(f"Invalid line:{line}")
            
            if "<==>" in rline:
                left, right = rline.split("<==>")
                mets_left = left.split("+")
                for met in mets_left:
                    met_id = met.strip()
                    if met_id not in gmr.nodes:
                        gmr.add_vertex_type(met_id, "metabolite")
                    if self.split_rev:
                        gmr.add_edge(met_id, reac_id)
                        gmr.add_vertex_type(reac_id+"_b", "reaction")
                        gmr.add_edge(reac_id+"_b", met_id)
                    else:
                        gmr.add_edge(met_id, reac_id)
                        gmr.add_edge(reac_id, met_id)
                mets_right = right.split("+")
                for met in mets_right:
                    met_id = met.strip()
                    if met_id not in gmr.nodes:
                        gmr.add_vertex_type(met_id, "metabolite")
                    if self.split_rev:
                        gmr.add_edge(met_id, reac_id+"_b")
                        gmr.add_edge(reac_id, met_id)
                    else:
                        gmr.add_edge(met_id, reac_id)
                        gmr.add_edge(reac_id, met_id)
            elif "-->" in line:
                left, right = rline.split("-->")
                mets_left = left.split("+")
                for met in mets_left:
                    met_id = met.strip()
                    if met_id not in gmr.nodes:
                        gmr.add_vertex_type(met_id, "metabolite")
                    gmr.add_edge(met_id, reac_id)
                mets_right = right.split("+")
                for met in mets_right:
                    met_id = met.strip()
                    if met_id not in gmr.nodes:
                        gmr.add_vertex_type(met_id, "metabolite")
                    gmr.add_edge(reac_id, met_id)
            else:
                raise Exception(f"Invalid line:{line}")    
        rf.close()
        
        if self.net_type == "metabolite-reaction": 
            self = gmr
        elif self.net_type == "metabolite-metabolite":
            self.convert_metabolite_net(gmr)
        elif self.net_type == "reaction-reaction": 
            self.convert_reaction_graph(gmr)
        else:
            self.graph = {}
        
        
    def convert_metabolite_net(self, gmr):
        for m in gmr.node_types["metabolite"]:
            self.add_vertex(m)
            for s in gmr.get_successors(m):
                sucs_r = gmr.get_successors(s)
                for s2 in sucs_r:
                    if m != s2: 
                        self.add_edge(m, s2)
    
    def summary_of_topology(self):
        summary = {
            "Node":[],"K":[],
            "B":[],"C":[],"CC":[]
        }
        all_between = self.all_betweenness_centrality()
        all_clust_coef = self.all_clustering_coefs()
        all_degree = self.all_degrees("inout")
        all_close = self.all_closeness_centrality()
        for node in self.nodes:
            summary["Node"].append(node)
            summary["K"].append(all_degree[node])
            summary["B"].append(all_between[node])
            summary["C"].append(all_close[node])
            summary["CC"].append(all_clust_coef[node])

        return summary

def run_sample():
    file = "MN.txt"
    MN = MetabolicNetwork("metabolite-metabolite")
    MN.load_from_file(file)
    print("Finsh loading file")

    import time 
    t1 = time.time()
    summary = MN.summary_of_topology()
    t2 = time.time()
    print(print("Finish calculate {} node in {:0.5f} second".format(
                len(MN.nodes),t2-t1)))

    import pandas as pd
    df = pd.DataFrame(summary)
    df.sort_values(by="K",ascending=False,inplace=True)
    print(df[:10])
    df.to_csv("MN-summary.csv",index=False)


if __name__ == "__main__":
    import os
    path = os.path.dirname(__file__)
    os.chdir(path)

    run_sample()
